package cn.exrick.xboot.modules.captchaLogin.controller;

import cn.exrick.xboot.common.constant.CommonConstant;
import cn.exrick.xboot.common.constant.SecurityConstant;
import cn.exrick.xboot.common.jiuqiCommon.callAPIUtil.CallSMSservice;
import cn.exrick.xboot.common.qywxCode.CreateRandomNums;
import cn.exrick.xboot.common.qywxCode.Security.service.MyUserDetailsService;
import cn.exrick.xboot.common.utils.ResultUtil;
import cn.exrick.xboot.common.utils.SecurityUtil;
import cn.exrick.xboot.common.utils.SpringContextUtil;
import cn.exrick.xboot.common.vo.Result;
import cn.exrick.xboot.common.vo.TokenUser;
import cn.exrick.xboot.config.redis.RedisRepository;
import cn.exrick.xboot.modules.base.dao.UserDao;
import cn.exrick.xboot.modules.base.entity.User;
import cn.exrick.xboot.modules.base.entity.UserRole;
import cn.exrick.xboot.modules.base.service.UserService;
import cn.exrick.xboot.modules.base.service.mybatis.IUserRoleService;
import cn.exrick.xboot.modules.callApi.entity.SMS;
import cn.hutool.core.util.StrUtil;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author    : LiYuanzhuo
 * description: 短信验证码登录
 * create time: 2019/11/4 17:10
 */
@RestController
@RequestMapping(value = "/xboot/smsLogin")
@Slf4j
public class SmsVerifyLoginController {

    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisRepository redisRepository;
    @Autowired
    private CallSMSservice callSMSservice;
    @Resource
    private MyUserDetailsService myUserDetailsService;
    @Autowired
    private UserDao userDao;

    @Value("${xboot.tokenExpireTime}")
    private Integer tokenExpireTime;

    @Value("${xboot.saveLoginTime}")
    private Integer saveLoginTime;

    @Value("${xboot.token.storePerms}")
    private Boolean storePerms;

    @Autowired
    private IUserRoleService iUserRoleService;

    /**
     * @author    : LiYuanzhuo
     * description: 发送短信验证码
     * create time: 2019/11/4 17:15
     */
    @PostMapping(value = "/sendCode")
    public Result<Object> sendSMSCode(@RequestParam String username){

        if (username == null) {
            return new ResultUtil<>().setErrorMsg("用户名为空！");
        }

        User user = userService.findByUsername(username);

        if (user == null){
            user = userService.findByMobile(username);

            if (user ==null) {
                return new ResultUtil<>().setErrorMsg("该用户不存在！");
            }
            List<User> userList= userDao.findByMobile(username);
            if (userList.size()>1){
                return new ResultUtil<Object>().setErrorMsg("该手机号绑定了多个账户，请使用身份证号登录！");
            }

        }

        if (user.getStatus().equals(CommonConstant.USER_STATUS_LOCK)){
            return new ResultUtil<Object>().setErrorMsg("该用户已经被禁用！请联系管理员！");
        }


        username = user.getUsername();


        if (null == user.getMobile() || "" == user.getMobile()){
            return new ResultUtil<>().setErrorMsg("未找到用户手机号！");
        }
        //发送验证码
        String cmsCode = CreateRandomNums.createRandomNum(6);
        SMS sms = new SMS();
        sms.setDESTADDR(user.getMobile());
        /**
         * Modify 20191225 njp 更换短信平台（发送模板短信）begin
         */
        sms.setMESSAGECONTENT("登录验证码:" + cmsCode);
        //sms.setMESSAGECONTENT(cmsCode);
        /**
         * Modify 20191225 njp 更换短信平台（发送模板短信）end
         */
        boolean sendCMSCode = callSMSservice.sendSMS(sms);

        if(sendCMSCode == false){
            return new ResultUtil<>().setErrorMsg("验证码发送失败！");
        }
        //发送成功将验证码存放到redis，以备验证
        redisTemplate = (RedisTemplate) SpringContextUtil.getBean("redisTemplate");
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(stringSerializer);

        //验证码写死了。供测试使用，生产需要更改
        redisTemplate.opsForValue().set(CommonConstant.WEB_CMS_CODE + username, cmsCode, 300, TimeUnit.SECONDS);
        log.info("WEB用户{},手机号为{},调用发送短信验证码接口,验证码为{}",username,user.getMobile(),cmsCode);

        return new ResultUtil<>().setSuccessMsg("验证码已发送");
    }

    /**
     * @author    : LiYuanzhuo
     * description: web端使用短信验证码登录
     * create time: 2019/11/4 17:15
     */
    @PostMapping(value = "/verifyLogin")
    public Result<Object> smsLogin(@RequestParam String username,@RequestParam String code,
                                   HttpServletRequest httpRequest){

        User user = userService.findByUsername(username);
        if (user == null){
            user = userService.findByMobile(username);
        }
        if (user ==null){
            return new ResultUtil<>().setErrorMsg("该用户不存在！");
        }else {
            username = user.getUsername();
        }

        String cmsCode = redisRepository.get(CommonConstant.WEB_CMS_CODE + username);

        if (!code.equals(cmsCode) ){
            return new ResultUtil<>().setErrorMsg("请输入正确的验证码!");
        }else {
            //验证成功，删除验证码
            redisTemplate.delete(CommonConstant.WEB_CMS_CODE + username);
        }

        String token = UUID.randomUUID().toString().replace("-", "");

        SecurityUtil securityUtil = new SecurityUtil();
        //用户权限放置
        List<GrantedAuthority> authorities = securityUtil.getCurrUserPerms(username);

        List<String> list = new ArrayList<>();
        for(GrantedAuthority g : authorities){
            list.add(g.getAuthority());
        }
        TokenUser users = new TokenUser(username, list, false);

        UserDetails userDetails = myUserDetailsService.loadUserByUsername(user);
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
        SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_THREADLOCAL);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        // 单点登录 之前的token失效
        String oldToken = stringRedisTemplate.opsForValue().get(SecurityConstant.USER_TOKEN + username);
        if(StrUtil.isNotBlank(oldToken)){
            redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken);
        }
        redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + username, token, tokenExpireTime, TimeUnit.MINUTES);
        redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(users), tokenExpireTime, TimeUnit.MINUTES);

        /**
         * njp 20190925 add
         * 添加三权分立开发中的超级管理员与审批员账号的判断 begin
         */
        AdminFlag adminFlag= new AdminFlag();
        UserRole userRole = new UserRole();
        userRole.setRoleId(CommonConstant.APPROVAL_ROLRID);
        userRole.setUserId(userService.findByUsername(username).getId());
        if("admin".equals(username)){
            //查询是否有审批员
            if(iUserRoleService.findUserRoleByRoleId(userRole).size()>0){
                log.info("超级管理员账号（并系统中存在审批员）");
                adminFlag.isRole="adminY";
            }else{
                log.info("超级管理员账号（并系统中不存在审批员需要注册）");
                adminFlag.isRole="adminN";
            }
            //}else if(new SsoLoginValidate().getApprovalRole(iUserRoleService.findUserRoleByUserId(userRole))){//检测账户是否是审批员的角色
        }else if(iUserRoleService.getApprovalRole(user)){//检测账户是否是审批员的角色(重新封装)
            log.info("该账户"+username+"是审批员");
            adminFlag.isRole="assessor";
        }

        Map map = new HashMap();

        map.put("token",token);
        map.put("adminFlag",adminFlag);

        return new ResultUtil<>().setData(map,"登录成功");
    }

    class AdminFlag{
        public String isRole="other";
    }
}
